// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_NEW_TAB_PAGE_CHROME_COLORS_CHROME_COLORS_SERVICE_H_
#define CHROME_BROWSER_NEW_TAB_PAGE_CHROME_COLORS_CHROME_COLORS_SERVICE_H_

#include "base/callback.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/themes/theme_service.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/web_contents.h"
#include "third_party/skia/include/core/SkColor.h"

class TestChromeColorsService;

namespace chrome_colors {

// These constants have to match the values of ChromeColorsInfo in enums.xml.
extern const int kDefaultColorId;
extern const int kOtherColorId;

// Supports theme changes originating from the NTP customization menu. Users can
// apply a Chrome color or the default theme, which will then either be reverted
// or confirmed and made permanent. If third party themes are present, users
// will also have a choice to permanently uninstall it.
// This service only works for Google NTP.
class ChromeColorsService : public KeyedService {
 public:
  explicit ChromeColorsService(Profile* profile);

  ChromeColorsService(const ChromeColorsService&) = delete;
  ChromeColorsService& operator=(const ChromeColorsService&) = delete;

  ~ChromeColorsService() override;

  // Returns id for the given |color| if it is in the predefined set, and
  // |kOtherColorId| otherwise.
  static int GetColorId(const SkColor color);

  // Record installed color id to UMA histogram. If |color| is not in the
  // predefined set, |kOtherColorId| is recorded.
  static void RecordColorOnLoadHistogram(SkColor color);

  // Applies a theme that can be reverted by saving the previous theme state and
  // the |tab| that changes are made from.
  void ApplyDefaultTheme(content::WebContents* tab);
  void ApplyAutogeneratedTheme(SkColor color, content::WebContents* tab);

  // Reverts to the previous theme state before first Apply* was used. Called
  // because user action on colors menu.
  void RevertThemeChanges();

  // Same as |RevertThemeChanges| but only reverts theme changes if they were
  // made from the same tab. Used for reverting changes from a closing NTP.
  void RevertThemeChangesForTab(content::WebContents* tab);

  // Confirms current theme changes. Since the theme is already installed by
  // Apply*, this only clears the previously saved state.
  void ConfirmThemeChanges();

 private:
  friend class ::TestChromeColorsService;

  // Reverts to the previous theme state unconditionally.
  void RevertThemeChangesInternal();

  // Saves the necessary state(revert callback and the current tab) for
  // performing theme change revert. Saves the state only if it is not set.
  void SaveThemeRevertState(content::WebContents* tab);

  // KeyedService implementation:
  void Shutdown() override;

  const raw_ptr<ThemeService> theme_service_;

  // The first tab that used Apply* and hasn't Confirm/Revert the changes.
  raw_ptr<content::WebContents> dialog_tab_ = nullptr;

  // Used for reverting back to the previously installed theme.
  std::unique_ptr<ThemeService::ThemeReinstaller> prev_theme_reinstaller_;

  base::WeakPtrFactory<ChromeColorsService> weak_ptr_factory_{this};
};

}  // namespace chrome_colors

#endif  // CHROME_BROWSER_NEW_TAB_PAGE_CHROME_COLORS_CHROME_COLORS_SERVICE_H_
